/* classe implementant le type vecteur dans l'espace (3D) */

public class Vecteur extends Matrice {

	/* Definition de l'exception d'erreur de format de la matrice pour les vecteurs*/
	class ErrNotVector extends IllegalArgumentException 
	{	ErrNotVector(Matrice m)
		{	System.out.println("La matrice definie n'est pas un vecteur de l'espace : matrice "+m.nbLignes()+"x"+nbColonnes()); }
	}

	/* Constructeurs */
	public Vecteur(double[][] tab)
	{	super(tab);
		if(nbLignes()!=3||nbColonnes()!=1)
		{	throw new ErrNotVector(this);} 
	}
	
	public Vecteur(double x, double y, double z)
	{	super(new double[3][1]);
		coeff[0][0] = x;
		coeff[1][0] = y;
		coeff[2][0] = z;
	}
	
	public Vecteur(Point3D a, Point3D b) {
		super(new double[3][1]);
		coeff[0][0] = b.x - a.x;
		coeff[1][0] = b.y - a.y;
		coeff[2][0] = b.z - a.z;
	}
	
	/** renvoie une des coordonnées du vecteur courant
	 * @param i un entier compris entre 1 et 3
	 * @return la i-ième coordonnée du vecteur courant
	 */
	public double get(int i) {
		if(i<1||i>3) { throw new IndexOutOfBoundsException("Entree invalide !");}
		return coeff[i-1][0];
	}
	
	/** Affiche les coordonnees du vecteur courant sur le terminal */
	public void affiche() {
		System.out.println(get(1)+" "+get(2)+" "+get(3)); 
	}

	/** Renvoie la norme du vecteur
	 * @return la norme euclidienne du vecteur courant */
	public double norme() {
		return Math.sqrt(get(1)*get(1)+get(2)*get(2)+get(3)*get(3));
	}
	
	/** Renvoie le resultat de l'operation definie par la matrice operation sur le vecteur courant
	 * @param operation une matrice 3*3
	 * @return le resultat de l'operation definie par la matrice operation sur le vecteur courant
	 */
	public Vecteur applique(Matrice operation) {
		return new Vecteur(operation.produit(this).getCoeff());
	}

	/** Renvoie le resultat de la rotation du vecteur courant autour de l'axe Oy
	 *  @param a un reel (degre)
	 *  @return le resultat de la rotation d'angle a du vecteur courant autour de l'axe Oy */
	public Vecteur rotationY(double a)
	{	return rotation(new Vecteur(0,1,0),a);}
	
	/** Renvoie le resultat de la rotation du vecteur courant autour de l'axe dirige par v
	 * @param v un vecteur
	 * @param a un reel (degre)
	 * @return le resultat de la rotation d'angle a du vecteur courant autour de l'axe dirige par v */
	public Vecteur rotation(Vecteur v, double a) {
		return applique(rotationM(v,a));
	}
	
	/** Renvoie le resultat du produit vectoriel du vecteur courant par v
	 * @param v un vecteur
	 * @return le vecteur courant vectoriel v */
	public Vecteur vectoriel(Vecteur v) {
		double x = get(2)*v.get(3) - get(3)*v.get(2),
			   y = get(3)*v.get(1) - get(1)*v.get(3),
			   z = get(1)*v.get(2) - get(2)*v.get(1);
		return new Vecteur(x,y,z);
	}
	
	/** Renvoie le resultat du produit du vecteur courant par un scalaire c
	 * @param c un reel
	 * @ return c*v  ou v est le vecteur courant */
	public Vecteur produit(double c) {
		double x = c*get(1),
			   y = c*get(2),
			   z = c*get(3);
		return new Vecteur(x,y,z);
	}

	/* programme de test */
	public static void main(String[] args) {

		System.out.println("Vecteur v");
		double[][] tab = {{1},{2},{3}};
		Vecteur v = new Vecteur(tab);
		v.affiche();
		
		double a = 180;

		System.out.println("rotation de "+a+" degres autour de Ox");
		double[][] t = {{3},{0},{0}};
		v.rotation(new Vecteur(t),a).affiche();

		System.out.println("rotation de "+a+" degres autour de Oy");
		v.rotationY(a).affiche();
	
	}

}